package processor;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.LockModeType;

import play.db.jpa.JPA;
import play.libs.F.Callback0;
import prefix.util.JPAUtil;

import models.Cart;
import models.CartItem;
import models.Loan;
import models.Order;
import models.OrderDetail;
import service.CartService;
import service.exception.OrderException;
import service.exception.OrderException.CODE;
import service.impl.OrderServiceImpl;

public class OrderProcessor extends OrderServiceImpl {

    public OrderProcessor(Order order) {
        super(order);
    }

    public OrderProcessor() {
    }

    public void submitOrder(CartService cart) throws OrderException {
        try {
            JPAUtil.beginTransaction();
            Cart mCart = cart.getDbcart();
            this.validate(mCart);
            Order order = new Order(mCart.getAid(), mCart.getAmount(), mCart.getId());
            this.setDborder(order);
            order.setStatus(Order.Status.COMMITTED);
            JPAUtil.em().persist(this.getDborder());
            this.checkoutCart(mCart.getListItems());
            mCart.setStatus(Cart.Status.CHECK_OUT);
            mCart.setUpdateD(new Date());
            JPAUtil.em().persist(this.getDborder());
            mCart.setOrderId(this.getDborder().getId());
            JPAUtil.em().merge(mCart);
            JPAUtil.commitTransaction();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            throw new OrderException(e, CODE.UNKNOWN);
        } finally {
            JPAUtil.closeEM();
        }
    }

    private void validate(Cart cart) throws OrderException {

    }

    private void checkoutCart(List<CartItem> items) throws OrderException {
        List<OrderDetail> detailList = new ArrayList<OrderDetail>();
        for (CartItem item : items) {
            OrderDetail detail = new OrderDetail();
            detail.setAmount(item.getAmount());
            detail.setLoanId(item.getLoanId());
            detail.setOrderId(this.dbOrder.getId());
            JPAUtil.em().persist(detail);
            item.setStatus(CartItem.Status.CHECK_OUT);
            item.setStatusD(new Date());
            item.setUpdateD(new Date());
            Loan loan = JPAUtil.em().find(Loan.class, item.getLoanId(), LockModeType.PESSIMISTIC_WRITE);
            double amountLeft = loan.getAppAmount() - loan.getAmount();
            if (amountLeft < item.getAmount())
                throw new OrderException(CODE.CHECKOUT_AMOUNT_MORE_THAN_LEFT);
            loan.setAmount(loan.getAmount() + item.getAmount());
            loan.setUpdateD(new Date());
            processFullyFundingLoan(loan);
            detailList.add(detail);
        }
        this.dbOrder.setDetailList(detailList);
    }

    private void processFullyFundingLoan(Loan loan) {
        if (loan.getAmount() == loan.getAmount()) {
            loan.setStatus(Loan.Status.REVIEW_FINAL);
            loan.setStartD(new Date());
        }
    }

}
